/*
 * Copyright 2000-2011 Worth Enterprises, Inc. All Rights Reserved.
 */
package com.worthent.foundation.util.state.provider;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.worthent.foundation.util.state.StateDef;
import com.worthent.foundation.util.state.StateDefException;
import com.worthent.foundation.util.state.StateErrorHandler;
import com.worthent.foundation.util.state.StateEvent;
import com.worthent.foundation.util.state.StateTable;
import com.worthent.foundation.util.state.StateTableData;
import com.worthent.foundation.util.state.StateTableDef;
import com.worthent.foundation.util.state.StateTransitioner;

/**
 * Provides an in-memory implementation of the state table instance.
 * 
 * @author Erik K. Worth
 * @version $Id: InMemoryStateTable.java 2 2011-11-28 00:10:06Z erik.k.worth@gmail.com $
 */
public class InMemoryStateTable implements StateTable {

    /** Logger used for this class */
    private static final Logger LOGGER =
        LoggerFactory.getLogger(InMemoryStateTable.class);

    /** The state table error handler to use */
    private static final StateErrorHandler ERROR_HANDLER =
        new LoggingStateErrorHandler(LOGGER);

    /** The state transitioner to use */
    private static final StateTransitioner STATE_TRANSITIONER =
        new LoggingStateTransitioner(LOGGER);

    /** The state table definition */
    protected final StateTableDef stateTblDef;

    /** Keeps track of current and prior state table state */
    protected final StateTableData dataObject;

    /**
     * Constructs the state table instance with the table definition and the
     * initial state table history object.
     * 
     * @param stateTblDef the state table definition
     * @param dataObject the initial state table history
     */
    public InMemoryStateTable(
        final StateTableDef stateTblDef,
        final StateTableData dataObject) throws StateDefException {
        this.stateTblDef = stateTblDef;
        this.dataObject = dataObject;
    }

    /**
     * Constructs the state table instance with the table definition and an
     * initial instance of the default state history object.
     * 
     * @param stateTblDef the state table definition
     */
    public InMemoryStateTable(final StateTableDef stateTblDef)
        throws StateDefException {
        this(stateTblDef, new StateTableData());
    }

    //
    // StateTable
    //

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.worthent.foundation.core.util.state.StateTable#getStateTableName()
     */
    @Override
    public String getStateTableName() {
        return stateTblDef.getName();
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.worthent.foundation.core.util.state.StateTable#getErrorHandler()
     */
    @Override
    public StateErrorHandler getErrorHandler() {
        return ERROR_HANDLER;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.worthent.foundation.core.util.state.StateTable#getTransitioner()
     */
    @Override
    public StateTransitioner getTransitioner() {
        return STATE_TRANSITIONER;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.worthent.foundation.core.util.state.StateTable#
     * initializeStateTableData()
     */
    @Override
    public void initializeStateTableData() throws StateDefException {
        final StateDef initialState = stateTblDef.getInitialState();
        final String initStateName = initialState.getName();
        dataObject.setCurrentState(initStateName);
        dataObject.setPriorState(initStateName);
    }

    /**
     * Returns a copy of the state history. Overload this if you extend
     * {@link StateTableData}. The default implementation calls the copy
     * constructor on <code>StateHistory</code>.
     * 
     * @param event unused
     * 
     * @return a copy of the state history
     */
    @Override
    public StateTableData getStateTableData(final StateEvent event) {
        return new StateTableData(dataObject);
    }

    /**
     * Copies the state from the specified data object into the one maintained
     * by this state table instance.
     * 
     * @param event unused
     * 
     * @param dataObject the new state table data
     */
    @Override
    public void setStateTableData(
        final StateEvent event,
        final StateTableData dataObject) {

        // Copy the in-memory history state from the provided one
        this.dataObject.set(dataObject);
    }

    /** Returns the state table definition */
    @Override
    public StateTableDef getStateTableDefinition(final StateEvent event) {
        return stateTblDef;
    }

}
